#ifndef __LINEARSOLVER_H__
#define __LINEARSOLVER_H__

#include "matvec.h"
#include "multilevel.h"

typedef struct LINEARSOLVER_
{
    // 求解器类型
    SOLVERTYPE solvertype;
    // 设置(√改动)
    DOUBLE rtol, atol; // relative & absolute tolerance
    INT maxitr;        // max iteration number
    // 一些可能需要的结果(x改动)
    INT calltimes;
    DOUBLE residualnorm;
    // 数据
    MATRIX *matrix;
    VECTOR *vector_rhs;
    VECTOR *vector_sol;
    MULTILEVEL *multilevel;
    bool alreadysetup;
    // 实现
    void *ops;
    void *data;
} LINEARSOLVER;

typedef struct LINEARSOLVER_OPS_
{
    void (*setup)(LINEARSOLVER *);
    void (*solve)(LINEARSOLVER *);
    void (*destory)(LINEARSOLVER *);
} LINEARSOLVER_OPS;

void LinearSolverCreate(LINEARSOLVER **linearsolver, SOLVERTYPE type);
void LinearSolverSetType(LINEARSOLVER *linearsolver, SOLVERTYPE type);
void LinearSolverSetUp(LINEARSOLVER *solver, MATRIX *matrix);
void LinearSolve(LINEARSOLVER *solver, MATRIX *matrix, VECTOR *rhs, VECTOR *solution);
void LinearSolverReSet(LINEARSOLVER *linearsolver, MATRIX *matrix);
void LinearSolverDestroy(LINEARSOLVER **linearsolver);

// multilevel
void LinearSolverMultiLevelSetUp(LINEARSOLVER *solver, MULTILEVEL *multilevel);
void LinearSolveMultiLevel(LINEARSOLVER *solver, MULTILEVEL *multilevel);
void LinearSolverMultiLevelReSet(LINEARSOLVER *linearsolver, MULTILEVEL *multilevel);

#if defined(PETSC_USE)
void LinearSolverCreate_PETSc_KSPCG(LINEARSOLVER *linearsolver);
void LinearSolverCreate_PETSc_SUPERLU(LINEARSOLVER *linearsolver);
#endif
void LinearSolverCreate_MultiLevel(LINEARSOLVER *linearsolver);

/////////////////////////////////////////////////////////////////////////////
/*                    一些针对某种解法器的可设置参数                          */
/////////////////////////////////////////////////////////////////////////////
#define OpenPFEM_DEFAULT 0x80000000
void LinearSolverMultiLevelSetLevel(LINEARSOLVER *solver, INT initial_level, INT coarse_level, INT fine_level);

#endif